/*
 * SPDX-FileCopyrightText: 2022-2024 Andrew Gunnerson
 * SPDX-License-Identifier: GPL-3.0-only
 */

@file:OptIn(ExperimentalUnsignedTypes::class)

package com.sanji.audio_test.format

import android.content.Context
import com.sanji.audio_test.R

/**
 * 格式参数信息抽象基类
 * 
 * 定义了格式参数的基本属性和方法，用于验证、格式化和处理格式特定的参数
 * 
 * @param default 默认参数值
 * @param presets 一些精选的参数选择，用于在UI中显示为预设选项
 */
sealed class FormatParamInfo(
    val default: UInt,
    /** 一些精选的参数选择，用于在UI中显示为预设选项 */
    val presets: UIntArray,
) {
    /**
     * 确保 [param] 参数有效
     *
     * @throws IllegalArgumentException 如果 [param] 无效
     */
    abstract fun validate(param: UInt)

    /**
     * 将可能无效的 [param] 值转换为最接近的有效值
     */
    abstract fun toNearest(param: UInt): UInt

    /**
     * 格式化 [param] 以呈现为面向用户的字符串
     */
    abstract fun format(context: Context, param: UInt): String
}

/**
 * 范围参数类型枚举
 */
enum class RangedParamType {
    /** 压缩级别 */
    CompressionLevel,
    /** 比特率 */
    Bitrate,
}

/**
 * 范围参数信息类
 * 
 * 用于处理具有特定范围的参数，如压缩级别或比特率
 * 
 * @param type 参数类型
 * @param range 参数有效范围
 * @param default 默认参数值
 * @param presets 预设参数值数组
 */
class RangedParamInfo(
    val type: RangedParamType,
    val range: UIntRange,
    default: UInt,
    presets: UIntArray,
) : FormatParamInfo(default, presets) {
    /**
     * 验证参数是否在有效范围内
     * 
     * @param param 待验证的参数
     * @throws IllegalArgumentException 如果参数不在有效范围内
     */
    override fun validate(param: UInt) {
        if (param !in range) {
            throw IllegalArgumentException("参数 $param 不在范围内: " +
                    "[${range.first}, ${range.last}]")
        }
    }

    /** 将 [param] 限制在 [range] 范围内 */
    override fun toNearest(param: UInt): UInt = param.coerceIn(range)

    /**
     * 格式化参数为用户友好的字符串
     * 
     * @param context 上下文对象
     * @param param 参数值
     * @return 格式化后的字符串
     */
    override fun format(context: Context, param: UInt): String =
        when (type) {
            RangedParamType.CompressionLevel ->
                "Level $param"
            RangedParamType.Bitrate -> {
                // 如果参数是1000的倍数，以kbps显示，否则以bps显示
                if (param % 1_000U == 0U) {
                    "${param / 1_000U} kbps"
                } else {
                    "$param bps"
                }
            }
        }
}

/**
 * 无参数信息对象
 * 
 * 用于不需要参数的格式
 */
data object NoParamInfo : FormatParamInfo(0u, uintArrayOf()) {
    /**
     * 验证参数（总是有效）
     */
    override fun validate(param: UInt) {
        // 总是有效
    }

    /**
     * 转换为最近的有效值（总是有效）
     */
    override fun toNearest(param: UInt): UInt = param

    /**
     * 格式化参数为字符串（空字符串）
     */
    override fun format(context: Context, param: UInt): String = ""
}